package com.example.order.service;

import com.example.order.dto.OrderDTO;
import com.example.order.dto.OrderRequest;
import com.example.order.entity.Order;
import com.example.order.event.OrderCancelledEvent;
import com.example.order.event.OrderCreatedEvent;
import com.example.order.event.OrderPaidEvent;
import com.example.order.repository.OrderRepository;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.UUID;

@Service
public class OrderService {
    private final OrderRepository orderRepository;
    private final ApplicationEventPublisher eventPublisher;
    private final ActiveOrderManager activeOrderManager;

    public OrderService(OrderRepository orderRepository, 
                       ApplicationEventPublisher eventPublisher,
                       ActiveOrderManager activeOrderManager) {
        this.orderRepository = orderRepository;
        this.eventPublisher = eventPublisher;
        this.activeOrderManager = activeOrderManager;
    }

    /**
     * 创建订单
     */
    @Transactional
    public OrderDTO createOrder(OrderRequest request) {
        // 生成订单号
        String orderNo = generateOrderNo();
        
        // 创建订单实体
        Order order = new Order();
        order.setOrderNo(orderNo);
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setAmount(request.getAmount());
        order.setStatus("created");
        order.setCreateTime(LocalDateTime.now());
        
        // 保存订单
        Order savedOrder = orderRepository.save(order);
        
        // 更新活跃订单数量
        activeOrderManager.increment();
        
        // 发布订单创建事件
        eventPublisher.publishEvent(new OrderCreatedEvent(
                this, 
                orderNo, 
                savedOrder.getUserId(),
                savedOrder.getAmount()
        ));
        
        // 转换为DTO返回
        return convertToDTO(savedOrder);
    }

    /**
     * 支付订单
     */
    @Transactional
    public void payOrder(String orderNo, String paymentMethod) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderNo));
        
        if (!"created".equals(order.getStatus())) {
            throw new IllegalStateException("订单状态异常，无法支付: " + order.getStatus());
        }
        
        // 更新订单状态
        order.setStatus("paid");
        order.setPayTime(LocalDateTime.now());
        order.setPaymentMethod(paymentMethod);
        orderRepository.save(order);
        
        // 更新活跃订单数量
        activeOrderManager.decrement();
        
        // 发布订单支付事件
        eventPublisher.publishEvent(new OrderPaidEvent(
                this, 
                orderNo,
                paymentMethod,
                order.getAmount(),
                order.getCreateTime()
        ));
    }

    /**
     * 取消订单
     */
    @Transactional
    public void cancelOrder(String orderNo) {
        Order order = orderRepository.findByOrderNo(orderNo)
                .orElseThrow(() -> new IllegalArgumentException("订单不存在: " + orderNo));
        
        if (!"created".equals(order.getStatus())) {
            throw new IllegalStateException("订单状态异常，无法取消: " + order.getStatus());
        }
        
        // 更新订单状态
        order.setStatus("cancelled");
        orderRepository.save(order);
        
        // 更新活跃订单数量
        activeOrderManager.decrement();
        
        // 发布订单取消事件
        eventPublisher.publishEvent(new OrderCancelledEvent(
                this, 
                orderNo,
                order.getAmount()
        ));
    }

    /**
     * 生成唯一订单号
     */
    private String generateOrderNo() {
        return "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }

    /**
     * 转换实体为DTO
     */
    private OrderDTO convertToDTO(Order order) {
        OrderDTO dto = new OrderDTO();
        dto.setId(order.getOrderNo());
        dto.setUserId(order.getUserId());
        dto.setProductId(order.getProductId());
        dto.setAmount(order.getAmount());
        dto.setStatus(order.getStatus());
        dto.setCreateTime(order.getCreateTime());
        dto.setPayTime(order.getPayTime());
        dto.setPaymentMethod(order.getPaymentMethod());
        return dto;
    }
}
